﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;

namespace SkypeMonitorService
{
	[RunInstaller(true)]
	public partial class ProjectInstaller : System.Configuration.Install.Installer
	{
		public ProjectInstaller()
		{
			InitializeComponent();
		}

		protected override void OnBeforeInstall(IDictionary savedState)
		{
			base.OnBeforeInstall(savedState);

			Context.LogMessage("BeforeInstall");

			string serName = null;

			if (Context.Parameters.ContainsKey("sn"))
				serName = Context.Parameters["sn"];

			string serDisplayName = null;
			if (Context.Parameters.ContainsKey("sdn"))
				serDisplayName = Context.Parameters["sdn"];

			string productVersion = null;
			if (Context.Parameters.ContainsKey("pv"))
				productVersion = Context.Parameters["pv"];

			this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
			this.serviceProcessInstaller1.Username = null;
			this.serviceProcessInstaller1.Password = null;

			if (!string.IsNullOrEmpty(serName))
				this.serviceInstaller1.ServiceName = serName;
			if (!string.IsNullOrEmpty(serDisplayName))
				this.serviceInstaller1.DisplayName = serDisplayName;
		}

		protected override void OnAfterInstall(IDictionary savedState)
		{
			base.OnAfterInstall(savedState);
			Context.LogMessage("AfterInstall");

			string assmPath = string.Format("{0}{1}", Context.Parameters["asm"], ".config");
			Context.LogMessage("config file: " + assmPath);
			Context.LogMessage("config file is exist: " + System.IO.File.Exists(assmPath));
			if (!System.IO.File.Exists(assmPath))
				assmPath = System.IO.Path.Combine(Context.Parameters["td"], "Service\\SkypeMonitorService.exe.config");


			try
			{
				Context.LogMessage("Begin change attribute");
				System.Xml.Linq.XDocument doc = System.Xml.Linq.XDocument.Load(assmPath);
				doc.Root.Element("appSettings").Elements("add").First().Attribute("value").Value = Context.Parameters["td"];
				doc.Save(assmPath);
				Context.LogMessage("Changed successfully");
			}
			catch (Exception ex) { Context.LogMessage(ex.Message); }

			Context.LogMessage("Begin start service");
			System.ServiceProcess.ServiceController sc = System.ServiceProcess.ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.Contains("SkypeMonitorService"));
			if (sc != null && sc.Status == System.ServiceProcess.ServiceControllerStatus.Stopped)
			{
				try
				{
					sc.Start();
					sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running, TimeSpan.FromSeconds(10));
				}
				catch (System.ServiceProcess.TimeoutException ex) { Context.LogMessage(ex.Message); }
				catch (System.ComponentModel.Win32Exception ex) { Context.LogMessage(ex.Message); }
				catch (System.InvalidOperationException ex) { Context.LogMessage(ex.Message); }
			}

			try
			{
				Context.LogMessage("Begin set registry data");
				using (var registry = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string.Format(@"Software\{0}{1}", Context.Parameters["pn"], Context.Parameters["pv"]), Microsoft.Win32.RegistryKeyPermissionCheck.ReadWriteSubTree))
				{
					registry.SetValue("ServiceName", string.Format("{0}{1}", Context.Parameters["pn"], Context.Parameters["pv"]), Microsoft.Win32.RegistryValueKind.String);
					registry.Flush();
				}
				Context.LogMessage("Registry data set successfully");
			}
			catch (Exception ex) { Context.LogMessage(ex.Message); }

			try
			{
				System.Management.ConnectionOptions coOptions = new System.Management.ConnectionOptions();
				coOptions.Impersonation = System.Management.ImpersonationLevel.Impersonate;
				System.Management.ManagementScope mgmtScope = new
				System.Management.ManagementScope(@"root\CIMV2", coOptions);
				mgmtScope.Connect();
				System.Management.ManagementObject wmiService;
				string serName = Context.Parameters["sn"];
				Context.LogMessage("Service name to iterract with desktop: " + serName);
				wmiService = new System.Management.ManagementObject(string.Format("Win32_Service.Name='{0}'", serName));

				System.Management.ManagementBaseObject InParam = wmiService.GetMethodParameters("Change");
				InParam["DesktopInteract"] = true;
				System.Management.ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null);
			}
			catch (Exception ex) { Context.LogMessage(ex.Message); }
		}

		protected override void OnCommitted(IDictionary savedState)
		{
			base.OnCommitted(savedState);
			Context.LogMessage("Committed");

			string serName = string.Format("{0}{1}", Context.Parameters["pn"], Context.Parameters["pv"]);
			Context.LogMessage(serName);

			Context.LogMessage("Begin set registry data");
			using (Microsoft.Win32.RegistryKey ckey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(string.Format(@"SYSTEM\CurrentControlSet\Services\{0}", serName), true))
			{
				if (ckey != null && ckey.GetValue("Type") != null)
				{
					ckey.SetValue("Type", (((int)ckey.GetValue("Type")) | 256));
					ckey.Flush();
					Context.LogMessage("registry data set successfully");
				}
			}
		}

		protected override void OnBeforeUninstall(IDictionary savedState)
		{
			base.OnBeforeUninstall(savedState);

			string pn = Context.Parameters["pn"];
			string pv = Context.Parameters["pv"];

			System.ServiceProcess.ServiceController sc = System.ServiceProcess.ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.Contains(string.Format("{0} v{1}",
				pn, pv)));
			if (sc != null && (sc.Status == System.ServiceProcess.ServiceControllerStatus.Running))
			{
				try
				{
					sc.Stop();
					sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
				}
				catch (System.InvalidOperationException ex) { Context.LogMessage(ex.Message); }
				catch (System.ServiceProcess.TimeoutException ex) { Context.LogMessage(ex.Message); }
				catch (System.ComponentModel.Win32Exception ex) { Context.LogMessage(ex.Message); }
			}
		}

		public override void Uninstall(IDictionary savedState)
		{
			base.Uninstall(savedState);
			string pn = Context.Parameters["pn"];
			string pv = Context.Parameters["pv"];

			System.ServiceProcess.ServiceController sc = System.ServiceProcess.ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.Contains(string.Format("{0} v{1}",
				pn, pv)));
			if (sc != null && sc.Status == System.ServiceProcess.ServiceControllerStatus.Running)
			{
				try
				{
					sc.Stop();
					sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
				}
				catch (System.ServiceProcess.TimeoutException) { }
				catch (System.ComponentModel.Win32Exception) { }
				catch (System.InvalidOperationException) { }
			}
		}
	}
}
